`timescale 1ns/1ps
module ramfifo_tb();

	parameter	DATA_WIDTH	= 32	;
	parameter	ADDR_DEPTH	= 4	;
	parameter 	ADDR_WIDTH	= 	(ADDR_DEPTH <= 2)    ? 1  :
								(ADDR_DEPTH <= 4)    ? 2  :
								(ADDR_DEPTH <= 8)    ? 3  :
								(ADDR_DEPTH <= 16)   ? 4  :
								(ADDR_DEPTH <= 32)   ? 5  :
								(ADDR_DEPTH <= 64)   ? 6  :
								(ADDR_DEPTH <= 128)  ? 7  :
								(ADDR_DEPTH <= 256)  ? 8  :
								(ADDR_DEPTH <= 512)  ? 9  :
								(ADDR_DEPTH <= 1024) ? 10 :
								(ADDR_DEPTH <= 2048) ? 11 :
								(ADDR_DEPTH <= 4096) ? 12 :
								(ADDR_DEPTH <= 8192) ? 13 : 14;

	reg								clk					;
	reg								config_en			;
	reg								config_mode			;
	reg		[DATA_WIDTH-1 : 0]		ram_dina			;
	reg		[ADDR_WIDTH-1 : 0]		ram_addra			;
	reg								ram_wea				;
	reg		[DATA_WIDTH-1 : 0]		ram_dinb			;
	reg		[ADDR_WIDTH-1 : 0]		ram_addrb			;
	reg								ram_web				;
	
	reg								fifo_wr_clk			;
	reg								fifo_rd_clk			;
	reg		[DATA_WIDTH-1 : 0]		fifo_din   			;
	reg								fifo_wren  			;
	reg								fifo_rden  			;
	
	wire	[DATA_WIDTH-1 : 0]		ram_douta			;
	wire	[DATA_WIDTH-1 : 0]		ram_doutb			;
	wire	[DATA_WIDTH-1 : 0]		fifo_dout			;
	wire							fifo_full			;
	wire							fifo_empty			;
	wire							fifo_almost_full	;
	wire							fifo_almost_empty	;

	initial begin
		clk					= 1'b0;
		fifo_wr_clk			= 1'b0;
		fifo_rd_clk			= 1'b0;

		config_en			= 1'b0;
		config_mode			= 1'b0;
		ram_dina			= 32'd0;
		ram_addra			= 10'd0;
		ram_wea				= 1'b0;
		ram_dinb			= 32'd0;
		ram_addrb			= 10'd0;
		ram_web				= 1'b0;
		
		fifo_din   			= 32'd0;
		fifo_wren  			= 1'd0;
		fifo_rden  			= 1'd0;
		
		#1003
		config_en			= 1'b1;
		config_mode			= 1'b0;
		#10
		config_en			= 1'b0;

		#100
		ram_dina			= 32'd0;
		ram_addra			= 10'd0;
		ram_wea				= 1'b1;
		ram_dinb			= 32'd1;
		ram_addrb			= 10'd1;
		ram_web				= 1'b1;
		#10
		ram_dina			= 32'd2;
		ram_addra			= 10'd2;
		ram_wea				= 1'b1;
		ram_dinb			= 32'd3;
		ram_addrb			= 10'd3;
		ram_web				= 1'b1;
		#10
		ram_dina			= 32'd4;
		ram_addra			= 10'd4;
		ram_wea				= 1'b1;
		ram_dinb			= 32'd5;
		ram_addrb			= 10'd5;
		ram_web				= 1'b1;
		#10
		ram_dina			= 32'd6;
		ram_addra			= 10'd6;
		ram_wea				= 1'b1;
		ram_dinb			= 32'd7;
		ram_addrb			= 10'd7;
		ram_web				= 1'b1;
		#10
		ram_addra			= 10'd0;
		ram_wea				= 1'b0;
		ram_addrb			= 10'd1;
		ram_web				= 1'b0;
		#10
		ram_addra			= 10'd2;
		ram_addrb			= 10'd3;
		#10
		ram_addra			= 10'd4;
		ram_addrb			= 10'd5;
		#10
		ram_addra			= 10'd6;
		ram_addrb			= 10'd7;

		#200
		config_en			= 1'b1;
		config_mode			= 1'b1;
		#10
		config_en			= 1'b0;
	
		// case 1: 
		// write more data than FIFO can store, then read	
		#100
		fifo_wren			= 1'b1;
		fifo_din			= 32'd1;
		#10
		fifo_din			= 32'd2;
		#10
		fifo_din			= 32'd3;
		#10
		fifo_din			= 32'd4;
		#10
		fifo_din			= 32'd5;
		#10
		fifo_din			= 32'd6;
		#10
		fifo_wren			= 1'b0;
		fifo_rden			= 1'b1;
		#60
		fifo_rden			= 1'b0;

		// case 2: 
		// write data and read at same time
		#100
		fifo_wren			= 1'b1;
		fifo_din			= 32'd1;
		#10
		fifo_din			= 32'd2;
		#10
		fifo_din			= 32'd3;
		#10
		fifo_rden			= 1'b1;
		fifo_din			= 32'd4;
		#10
		fifo_din			= 32'd5;
		#10
		fifo_din			= 32'd6;
		#10
		fifo_wren			= 1'b0;
		fifo_rden			= 1'b1;
		#60

		#1000
		$finish;
	end

	always begin
		#5	
		clk				= !clk;
		fifo_wr_clk		= !fifo_wr_clk;
		fifo_rd_clk		= !fifo_rd_clk;
	end

	/*
	always @(posedge clk) begin
	end
	*/

	ramfifo ramfifo_inst(
		.clk				(clk			  ),
		.config_en			(config_en		  ),
		.config_mode		(config_mode	  ),
		.ram_dina			(ram_dina		  ),
		.ram_addra			(ram_addra		  ),
		.ram_wea			(ram_wea		  ),
		.ram_dinb			(ram_dinb		  ),
		.ram_addrb			(ram_addrb		  ),
		.ram_web			(ram_web		  ),
		.fifo_wr_clk		(fifo_wr_clk	  ),
		.fifo_rd_clk		(fifo_rd_clk	  ),
		.fifo_din			(fifo_din		  ),
		.fifo_wren			(fifo_wren		  ),
		.fifo_rden			(fifo_rden		  ),
											  
		.ram_douta			(ram_douta		  ),
		.ram_doutb			(ram_doutb		  ),
		.fifo_dout			(fifo_dout		  ),
		.fifo_full			(fifo_full		  ),
		.fifo_empty			(fifo_empty		  ),
		.fifo_almost_full	(fifo_almost_full ),
		.fifo_almost_empty	(fifo_almost_empty)
	);
endmodule
